package domain;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class DAOContact extends HibernateDaoSupport implements IDAOContact {
	
	/**
	 * Rajoute un contact dans la base de données
	 * 
	 * @param firstname
	 * @param lastname
	 * @param email
	 * @return renvoit le nouveau contact
	 */

	public Contact addContact(String firstname, String lastname, String email, Address address, Set<PhoneNumber> phones, String [] books, String SIRET) {

		Contact contact;

		if(SIRET != null && !SIRET.equals("")){
			contact = new Company();		
			((Company)contact).setSIRET(SIRET);
		} else {
			contact = new Contact();			
		}
		
		contact.setFirstName(firstname);
		contact.setLastName(lastname);
		contact.setEmail(email);
		contact.setAddress(address);
				
		
		if(books != null && books.length > 0){
			for(String book : books){
				
				ContactGroup contactGroup = (ContactGroup) DataAccessUtils.uniqueResult(getHibernateTemplate().find("from ContactGroup cg left join fetch cg.contacts where cg.groupName = '"+book+"'"));
				if(contactGroup == null){
					contactGroup = new ContactGroup();
					contactGroup.setGroupName(book);				
				}
				
				contact.addBook(contactGroup);		
			}			
		}
		
		
		if(phones.size() > 0){
			for(PhoneNumber phone : phones){
				contact.addPhone(phone);
			}
		}	
		
		getHibernateTemplate().save(contact);
		return contact;
	}

	/**
	 * Suppresion d'un contact à partir de son identifiant
	 * 
	 * @param id
	 * @return vrai si la suppression à bien été éffectuée
	 */

	public boolean deleteContact(long id) {
			Contact contact = getContact(id);
			Set<ContactGroup> tmp = new HashSet<ContactGroup>();
			tmp.addAll(contact.getBooks());
			for(ContactGroup contactGroup : tmp){
            	ContactGroup cg = (ContactGroup) DataAccessUtils.uniqueResult(getHibernateTemplate().find("from ContactGroup cg left join fetch cg.contacts where cg.groupName = '"+contactGroup.getGroupName()+"'"));
            	contact.removeBook(cg);
            	getHibernateTemplate().saveOrUpdate(cg);
            }             
            getHibernateTemplate().delete(contact);
			return true;		
	}

	/**
	 * Récupération d'un contact à partir de son identifiant
	 * 
	 * @param id
	 * @return
	 */
	
	public Contact getContact(long id) {
		return (Contact) DataAccessUtils.uniqueResult(getHibernateTemplate().find("from Contact c inner join fetch c.address left join fetch c.phones left join fetch c.books where c.id = "+id));
	}
	
	
	/**
	 * Récupération de tous les contacts
	 * 
	 * @return
	 */
	public List<Contact> getAllContact() {
		return getHibernateTemplate().find("from Contact");
	}

	/**
	 * Méthode qui modifie les coordonnées d'un contact
	 * 
	 * @param firstname
	 * @param lastname
	 * @param email
	 * @return
	 */
	public boolean modifyContact(long id, String firstname, String lastname, String email, Address address, Set<PhoneNumber> phones, String [] books, String SIRET) {
		
		Contact contact = getContact(id);
		
		if(SIRET != null && !SIRET.equals("")){
			if(contact instanceof Company){
				((Company)contact).setSIRET(SIRET);
			}
		}
		
		contact.setFirstName(firstname);
		contact.setLastName(lastname);
		contact.setEmail(email);

		contact.getAddress().setCity(address.getCity());
		contact.getAddress().setCountry(address.getCountry());
		contact.getAddress().setStreet(address.getStreet());
		contact.getAddress().setZip(address.getZip());
		
		int i;
		Set<ContactGroup> tmp = new HashSet<ContactGroup>();
		tmp.addAll(contact.getBooks());
		for(ContactGroup contactGroup : tmp){
			for(i=0; books != null && books.length > 0 && i<books.length && !books[i].equals(contactGroup.getGroupName()); i++);
			if(books == null || books.length == 0 || i == books.length){				
				ContactGroup cg = (ContactGroup) DataAccessUtils.uniqueResult(getHibernateTemplate().find("from ContactGroup cg left join fetch cg.contacts where cg.groupName = '"+contactGroup.getGroupName()+"'"));
				contact.removeBook(cg);
				getHibernateTemplate().saveOrUpdate(cg);
			}
        }          
		
		if(books != null && books.length > 0){
			for(String book : books){
				
				ContactGroup contactGroup = (ContactGroup) DataAccessUtils.uniqueResult(getHibernateTemplate().find("from ContactGroup cg left join fetch cg.contacts where cg.groupName = '"+book+"'"));
				if(contactGroup == null){
					contactGroup = new ContactGroup();
					contactGroup.setGroupName(book);				
				}
				
				contact.addBook(contactGroup);		
			}			
		}
		
		Set<PhoneNumber> contactPhones = contact.getPhones();
		for(PhoneNumber phoneNumber : contactPhones){
			boolean ok = false;
			for(PhoneNumber phone : phones){
				if(phoneNumber.getPhoneKind().equals(phone.getPhoneKind())){
					ok = true;
					break;
				}
			}
			if(!ok){
				getHibernateTemplate().delete(phoneNumber);				
			}
		}
		
		for(PhoneNumber phone : phones){
			boolean ok = false;
			for(PhoneNumber phoneNumber : contactPhones){
				if(phoneNumber.getPhoneKind().equals(phone.getPhoneKind())){
					phoneNumber.setPhoneNumber(phone.getPhoneNumber());
					ok = true;
					break;
				}
			}
			if(!ok){
				contact.addPhone(phone);				
			}	
		}
		try{
			getHibernateTemplate().saveOrUpdate(contact);			
		}
		catch(Exception e){
			return true;
		}
		
		return true;
	}

	/**
	 * Renvoit la liste des contacts correspondants au prénom
	 * 
	 * @param firstname
	 * @return
	 */
	public List<Contact> getContactByFirstName(String firstname) {
		
		List<Contact> contacts = getHibernateTemplate().findByCriteria(DetachedCriteria.forClass(Contact.class).add(Restrictions.like("firstName", firstname)).addOrder(Order.asc("id")));
		return contacts;
	}

	/**
	 * Renvoit la liste des contacts correspondants au nom
	 * 
	 * @param lastname
	 * @return
	 */
	public List<Contact> getContactByLastName(String lastname) {
		
		Contact contact = new Contact();
		contact.setLastName(lastname);		
		List<Contact> contacts = getHibernateTemplate().findByExample(contact);
		return contacts;
	}

	/**
	 * Renvoit la liste des contacts correspondants à l'email
	 * 
	 * @param email
	 * @return
	 */
	public List<Contact> getContactByEmail(String email) {
		List<Contact> contacts = getHibernateTemplate().findByCriteria(DetachedCriteria.forClass(Contact.class).add(Restrictions.like("email", email)).addOrder(Order.asc("id")));
		return contacts;
	}

	public List<ContactGroup> getAllBook() {
		return getHibernateTemplate().findByCriteria(DetachedCriteria.forClass(ContactGroup.class).addOrder(Order.asc("id")));
	}

}
